#include "app_buffer.h"
#include "string.h"
#include "stdlib.h"
#include "log.h"


/**
 * @brief 缓冲区初始化
 */
app_buffer_t *app_buffer_init(int sub_buff_data_size)
{
    //1 父缓冲区结构体初始化
    app_buffer_t *buffer = malloc(sizeof(app_buffer_t));

    //2 初始化子缓冲区
    for (int i = 0; i < 2; i++)
    {
         app_buffer_sub_t *sub_buffer = malloc(sizeof(app_buffer_sub_t));
         sub_buffer->data_prt = malloc(sub_buff_data_size);
         sub_buffer->total_len = sub_buff_data_size;
         sub_buffer->data_len = 0;

         buffer->sub_buffer[i] = sub_buffer;
    }
    
    //3 设定读写分区
    buffer->read_index = 0;
    buffer->write_index = 1;

    //4 初始化锁
     pthread_mutex_init(&buffer->read_lock, NULL);
     pthread_mutex_init(&buffer->swap_lock, NULL);

    return  buffer;
}


/**
 * @brief 向缓冲区进行写操作
 * @return  成功标志 0成功 -1 失败
 */
int app_buffer_write(app_buffer_t *buffer, uint8_t *write_data, int write_data_len)
{
     pthread_mutex_lock(&buffer->swap_lock);

    //1  取出当前负责写的缓冲区
    app_buffer_sub_t *sub_write_buffer = buffer->sub_buffer[buffer->write_index];
    //2 判断缓冲区是否有足够空间放入新的数据
    // 计算剩余空间
    int remain_size = sub_write_buffer->total_len - sub_write_buffer->data_len;
    if(remain_size < write_data_len)
    {
        log_error("缓冲区空间不足");
        return -1;
    }
    //3  写缓冲    3.1 写入数据长度作为帧头  3.2 拷贝数据  3.3  改变当前数据长度
    if(write_data_len > 255)
    {
        log_error("数据长度过大");
    }
    //b
    //3.1 写入数据长度作为帧头 
    sub_write_buffer->data_prt[sub_write_buffer->data_len] = write_data_len;
    //3.2拷贝数据
    memcpy(sub_write_buffer->data_prt+sub_write_buffer->data_len+1,write_data, write_data_len);
    // 3.3  改变当前数据长度
    sub_write_buffer->data_len += ( write_data_len+1);
    pthread_mutex_unlock(&buffer->swap_lock);
    return 0;
}


void swap_buffer_index(app_buffer_t *buffer)
{
    pthread_mutex_lock(&buffer->swap_lock);
    buffer->write_index = (  buffer->write_index ==0? 1:0  );
    buffer->read_index = (  buffer->read_index  ==0? 1:0 ) ;
    pthread_mutex_unlock(&buffer->swap_lock);
}

/**
 * @brief 向缓冲区进行写操作
 * @return  读取的字节数
 * 
 *     //1  取出当前负责读的缓冲区
    //2  判断数据是否有可读的数据
    // 2.1  判断缓冲区数据长度是否大于0
    // 2.2 如果可读长度为0 则进行分区切换
    // 2.3 再取一次当前负责读的缓冲区
    // 2.4 在进行数据长度判断 如果还是可读为0 则返回0
    // 3  如果可读 读取数据
    // 3.1    取出帧头数据长度 
    // 3.2    拷贝数据到read_buff
    // 3.3    把后面的数据覆盖前面的数据
    // 3.4    改变当前数据长度 
 */
int app_buffer_read(app_buffer_t *buffer, uint8_t *read_buff, int read_buff_len)
{

    // a 加锁    
    pthread_mutex_lock(&buffer->read_lock);

    //1  取出当前负责读的缓冲区
    app_buffer_sub_t *sub_read_buffer = buffer->sub_buffer[buffer->read_index];
 
    //2  判断数据是否有可读的数据 // 2.1  判断缓冲区数据长度是否大于0
    if(sub_read_buffer->data_len  == 0)
    { 
        // 2.2 如果可读长度为0 则进行分区切换
        swap_buffer_index(buffer);
        // 2.3 再取一次当前负责读的缓冲区
          sub_read_buffer = buffer->sub_buffer[buffer->read_index];
         // 2.4 在进行数据长度判断 如果还是可读为0 则返回0
         if(sub_read_buffer->data_len  == 0)
         {
            return 0; //确实没有数据
         }
    }

    // 3  如果可读 读取数据
    if(sub_read_buffer->data_len > read_buff_len)
    {
        log_error("临时数据容器长度不足");
        return -1;
    }
       // b 加锁
    // 3.1    取出帧头数据长度 
    int read_data_len = sub_read_buffer->data_prt[0];

    // 3.2    拷贝数据到read_buff
    memcpy(read_buff, sub_read_buffer->data_prt+1, read_data_len);
 
    // 3.3    把后面的数据覆盖前面的数据
    int del_len=read_data_len+1;
    memmove(sub_read_buffer->data_prt,sub_read_buffer->data_prt+del_len,sub_read_buffer->data_len-del_len);
    // 3.4    改变当前数据长度 
    sub_read_buffer->data_len -= del_len;
    pthread_mutex_unlock(&buffer->read_lock);

    return read_data_len;

}

/**
 * @brief 缓冲区销毁
 */
void app_buffer_destroy(app_buffer_t *buffer)
{
    // 先释放 子缓冲区
    for (int i = 0; i < 2; i++)
    {
          free(buffer->sub_buffer[i]->data_prt);
          free(buffer->sub_buffer[i] );
    }
    //释放锁
    pthread_mutex_destroy(&buffer->read_lock);
    pthread_mutex_destroy(&buffer->swap_lock);

    //是否 父缓冲区
    free(buffer);

}